package br.com.amadeus.android.business;


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONException;

import android.content.Context;
import android.text.Editable;
import android.util.Log;
import br.com.amadeus.android.activities.home.HomeActivity;
import br.com.amadeus.android.dao.ActionDAO;
import br.com.amadeus.android.dao.ConfigDAO;
import br.com.amadeus.android.dao.CourseDAO;
import br.com.amadeus.android.dao.CourseUserDAO;
import br.com.amadeus.android.dao.ForumDAO;
import br.com.amadeus.android.dao.GoalDAO;
import br.com.amadeus.android.dao.HistoryDAO;
import br.com.amadeus.android.dao.MessageDAO;
import br.com.amadeus.android.dao.ResourceDAO;
import br.com.amadeus.android.dao.RoleDAO;
import br.com.amadeus.android.dao.SocialHistoryDAO;
import br.com.amadeus.android.dao.TaskDAO;
import br.com.amadeus.android.dao.UserDAO;
import br.com.amadeus.android.entities.Action;
import br.com.amadeus.android.entities.Config;
import br.com.amadeus.android.entities.Course;
import br.com.amadeus.android.entities.CourseUser;
import br.com.amadeus.android.entities.Forum;
import br.com.amadeus.android.entities.Goal;
import br.com.amadeus.android.entities.Message;
import br.com.amadeus.android.entities.Resource;
import br.com.amadeus.android.entities.Role;
import br.com.amadeus.android.entities.SocialHistory;
import br.com.amadeus.android.entities.Task;
import br.com.amadeus.android.entities.User;
import br.com.amadeus.android.util.ConstantsAmadeusDroid;
import br.com.amadeus.android.util.ImageUtil;
import br.com.amadeus.android.util.Syncronizer;
import br.com.amadeus.android.util.SyncronizerHelper;

public class FacadeAmadeusDroid {

	protected static final String CATEGORIA = "curso";
	private static FacadeAmadeusDroid facadeAmadeusDroid = null;
	private GoalDAO goalDAO = null;
	private UserDAO userDAO = null;
	private TaskDAO taskDAO = null;
	private RoleDAO roleDAO = null;
	private ActionDAO actionDAO = null;
	private CourseDAO courseDAO = null;
	private ResourceDAO resourceDAO = null;
	private CourseUserDAO courseUserDAO = null;
	private ConfigDAO configDAO = null;
	private HistoryDAO historyDAO = null;
	private SocialHistoryDAO socialHistoryDAO = null;
	private ForumDAO forumDAO = null;
	private MessageDAO messageDAO = null;
	private Context ctx = null;
		
	public static FacadeAmadeusDroid getInstance(Context context) {
		if (facadeAmadeusDroid == null) {
			facadeAmadeusDroid = new FacadeAmadeusDroid(context);
		}
		return facadeAmadeusDroid;
	}
	
	private FacadeAmadeusDroid(Context context) {
		this.initializeSystem(context);	
	}

	public FacadeAmadeusDroid() {
	}

	private void initializeSystem(Context ctx) {
		// TODO Executar o SQL e preparar o Banco
		this.goalDAO = GoalDAO.getInstance(ctx);
		this.courseDAO = CourseDAO.getInstance(ctx);
		this.resourceDAO = ResourceDAO.getInstance(ctx);
		this.courseUserDAO = CourseUserDAO.getInstance(ctx);
		this.roleDAO = RoleDAO.getInstance(ctx);
		this.configDAO = ConfigDAO.getInstance(ctx);
		this.taskDAO = TaskDAO.getInstance(ctx);
		this.actionDAO = ActionDAO.getInstance(ctx);
		this.historyDAO = HistoryDAO.getInstance(ctx);
		this.socialHistoryDAO = SocialHistoryDAO.getInstance(ctx);
		this.forumDAO = ForumDAO.getInstance(ctx);
		this.messageDAO = MessageDAO.getInstance(ctx);
	}

	public void syncronizeAmadeus(ArrayList<Course> listCourses, ArrayList<CourseUser> listCourseUser, Config config, ArrayList<SocialHistory> listSocial) throws JSONException{
		
		int id_course = 0;
		int id_forum = 0;
						
		if (this.firstSyncronizing()) {
			for (Course course : listCourses) {
				id_course = (int) this.courseDAO.save(course);
				ArrayList<Resource> resourceList = course.getResourceList();
				for (Resource resource : resourceList) {
					if (resource.getForum() != null) {
						id_forum = (int) this.forumDAO.save(resource.getForum());
						resource.getForum().setId(id_forum);
						
						Forum forum = resource.getForum();
						ArrayList<Message> messages = forum.getListMessages();
						for (Message message : messages) {
							message.getForum().setId(id_forum);
							this.messageDAO.save(message);
						}
					}
					resource.getCourse().setId(id_course);
					this.resourceDAO.save(resource);
					
				}
				
				
			}

			for (CourseUser courseUser : listCourseUser) {
				this.courseUserDAO.save(courseUser);
			}
			
			this.configDAO.save(config);
			
			for (SocialHistory socialHistory : listSocial) {
				this.socialHistoryDAO.save(socialHistory);
			}
			
			initializeRoles();
			
		}else{
			//Implementação para Sincronização caso haja alterações nos dados em Amadeus WEB
			
			List<SyncronizerHelper> listSync = Syncronizer.getActionsSyncronize(getCoursesResources(), listCourses);
			
			boolean hasNews = false;
			for (SyncronizerHelper sync : listSync) {
				
				switch (sync.getAction()) {
				case SyncronizerHelper.INSERT:
					hasNews = true;
					if (sync.getTypeAction().equals(SyncronizerHelper.COURSE)) {
						
						List<Course> listNewCourses = sync.getCourseSyncList();
						for (Course course : listNewCourses) {
							
							id_course = (int) this.courseDAO.save(course);
							ArrayList<Resource> resourceList = course.getResourceList();
							for (Resource resource : resourceList) {
								resource.getCourse().setId(id_course);
								this.resourceDAO.save(resource);
							}
							
							int user_id = listCourseUser.get(0).getUser().getId();
							User user = new User(user_id);
							CourseUser courseUser = new CourseUser(0);
							course.setId(course.getId_amadeus());
							courseUser.setCourse(course);
							courseUser.setUser(user);
							this.courseUserDAO.save(courseUser);
						}
						
					}else if (sync.getTypeAction().equals(SyncronizerHelper.RESOURCE)) {
						
						List<Resource> listNewResources = sync.getResourceSyncList();
						for (Resource resource : listNewResources) {
							Course course = getCourseByResource(resource.getCourse().getId_amadeus());
							resource.getCourse().setId(course.getId());
							id_forum = 0;
							if (resource.getForum() != null) {
								id_forum = (int) this.forumDAO.save(resource.getForum());
								ArrayList<Message> listMessage = resource.getForum().getListMessages();
								for (Message message : listMessage) {
									message.getForum().setId(id_forum);
									this.messageDAO.save(message);
								}
							}
							if (id_forum != 0) {
								resource.getForum().setId(id_forum);
							}
							this.resourceDAO.save(resource);
							
						}
					}					
					break;
				case SyncronizerHelper.UPDATE:
					
					
					break;
				case SyncronizerHelper.DELETE:
					if (sync.getTypeAction().equals(SyncronizerHelper.COURSE)) {
						
						List<Course> listRemove = sync.getCourseSyncList();
						for (Course course : listRemove) {
							ArrayList<Resource> listResource = getListResourcesByCourse(course.getId());
							course.setResourceList(listResource);
							deleteCourse(course);
							deleteCourseUser(course);
						}
												
					}else if (sync.getTypeAction().equals(SyncronizerHelper.RESOURCE)) {
						
						List<Resource> listRemove = sync.getResourceSyncList();
						for (Resource resource : listRemove) {
							this.resourceDAO.delete(resource.getId());
							if (resource.getForum().getId() != 0) {
								this.forumDAO.delete(resource.getForum().getId());
								ArrayList<Message> listMessage = resource.getForum().getListMessages();
								for (Message message : listMessage) {
									this.messageDAO.delete(message.getId());
								}
							}
						}
					}
					
					break;
				}
			}
			
			if (hasNews) {
				Config cfg = getConfig();
				cfg.setVersionSync(1);
				this.configDAO.save(cfg);
				Log.i(CATEGORIA, "Has News Resource");
			}else{
				Config cfg = getConfig();
				cfg.setVersionSync(0);
				this.configDAO.save(cfg);
				Log.i(CATEGORIA, "No News Resource");
			}
			
		}
		
	}
	
	public int getUser(){
		return courseUserDAO.getUser();
	} 
	
	public boolean syncronizeTimeline(List<SocialHistory> listHistory) throws ClientProtocolException, IOException{
		boolean result = false;
		
		List<SyncronizerHelper> listSync = Syncronizer.getActionsSyncronizeTimeline(getListSocialHistory(), listHistory);
		if (listSync.size() > 0) {
			result = true;
		}
		Config cfg = getConfig();
		for (SyncronizerHelper sync : listSync) {
			List<SocialHistory> list = sync.getSocialHistories();
			for (SocialHistory hist : list) {
				this.socialHistoryDAO.save(hist);
				
				String endImageHist = cfg.getAmadeus_url() + 
	            ConstantsAmadeusDroid.HOST_AMADEUS_WEB_PHOTO + hist.getUserLogin();
            	ImageUtil.saveImageUser(endImageHist, hist.getUserName());
			}
		}
		
		return result;
	}
	
	public ArrayList<Goal> getAllGoalByCourse(int course_id){
		this.goalDAO = GoalDAO.getInstance(ctx);
		return this.goalDAO.getAllGoalByCourse(course_id); 
	}
	
	public boolean syncronizeForumMessages(ArrayList<Forum> listForum) {
		boolean result = false;
		
		List<SyncronizerHelper> listSync = Syncronizer.getActionsSyncronizeForum(getListForum(), listForum);
		if (listSync.size() > 0) {
			Log.i(CATEGORIA, "Has News Forum");
			result = true;
		}else{
			Log.i(CATEGORIA, "No News Forum");
		}
		
		for (SyncronizerHelper sync : listSync) {
			ArrayList<Message> list = sync.getListMessage();
			for (Message message : list) {
				this.messageDAO.save(message);
			}
		}
		
		return result;
	}

	public ArrayList<Forum> getListForum() {
		ArrayList<Forum> newForumList = new ArrayList<Forum>();
		ArrayList<Forum> forumList = this.forumDAO.getForumList();
		for (Forum forum : forumList) {
			ArrayList<Message> listMessage = this.messageDAO.getListMessagesByForum(forum.getId());
			forum.setListMessages(listMessage);
			newForumList.add(forum);
		}
		return newForumList;
	}

	public static FacadeAmadeusDroid getInstance() {
		if (facadeAmadeusDroid == null) {
			facadeAmadeusDroid = new FacadeAmadeusDroid();
		}
		return facadeAmadeusDroid;
	}
	
	public List<Course> getListActiveCourses(){
		return this.courseDAO.getListActiveCourses();
	}
	
	public List<Course> getListCourse(){
		return this.courseDAO.getListCourses();
	}
	
	public ArrayList<CourseUser> getListCourseUser(){
		return this.courseUserDAO.getListCourseUser();
	}
		
	public List<Course> getListInactiveCourses(){
		return this.courseDAO.getListInactiveCourses();
	}
	
	public ArrayList<Resource> getListResourcesByCourse(int course_id){
		return this.resourceDAO.getListResourcesByCourse(course_id);
	}
		
	public Forum getForum(int forum_id){
		return this.forumDAO.getForum(forum_id);
	}
	
	public ArrayList<Message> getListMessagesByForum(int forum_id){
		return this.messageDAO.getListMessagesByForum(forum_id);
	}
	
	public boolean firstSyncronizing(){
		if (this.courseDAO.getListCourses().size() == 0 &&
				this.resourceDAO.getListResources().size() == 0 &&
				this.courseUserDAO.getListCourseUser().size() == 0) {
			return true;
		}else{
			return false;
		}
	}
	
	public Course getCourse(int id){
		this.courseDAO = CourseDAO.getInstance(ctx);
		return this.courseDAO.getCourse(id);
	}
	
	public Course getCourseByAmadeusId(int amadeus_id){
		this.courseDAO = CourseDAO.getInstance(ctx);
		return this.courseDAO.getCourseByAmadeusId(amadeus_id);
	}
	
	public int getCourseByCourseUser(int course_user_id){
		this.courseUserDAO = CourseUserDAO.getInstance(ctx);
		return this.courseUserDAO.getCourseByCourseUser(course_user_id);
	}
		
	public int getCourseUser(int id_amadeus) {
		this.courseUserDAO = CourseUserDAO.getInstance(ctx);
		return this.courseUserDAO.getCourseUserByCourse(id_amadeus);
	}
	
	public CourseUser getCourseUserById(int id){
		return this.courseUserDAO.getCourseUser(id);
	}
	
	public Config getConfig(){
		return this.configDAO.getConfig();
	}
	
	public void deleteGoal(long goal_id){
		this.goalDAO.delete(goal_id);
	}
	
	public void deleteTask(int task_id){
		this.taskDAO.delete(task_id);
	}
		
	private void initializeRoles(){
		
		List<Role> listRoles = new ArrayList<Role>();
		
		Role r1 = new Role(0);
		r1.setAmadeus_id(0);
		r1.setValue(Role.ADMIN);
		listRoles.add(r1);
		
		Role r2 = new Role(0);
		r2.setAmadeus_id(0);
		r2.setValue(Role.ALUNO);
		listRoles.add(r2);
		
		Role r3 = new Role(0);
		r3.setAmadeus_id(0);
		r3.setValue(Role.MONITOR);
		listRoles.add(r3);
		
		Role r4 = new Role(0);
		r4.setAmadeus_id(0);
		r4.setValue(Role.PROFESSOR);
		listRoles.add(r4);
		
		for (Role role : listRoles) {
			this.roleDAO.save(role);
		}
	}
	
	private void deleteCourse(Course course){
		this.courseDAO.delete(course.getId());
		for (Resource resource : course.getResourceList()) {
			this.resourceDAO.delete(resource.getId());
		}
	}
	
	private void deleteCourseUser(Course course){
		List<CourseUser> list = this.courseUserDAO.getListCourseUserByCourse(course.getId_amadeus());
		for (CourseUser courseUser : list) {
			this.courseUserDAO.delete(courseUser.getId());
		}
	}
	
	private List<Course> getCoursesResources(){
		ArrayList<Course> courses = new ArrayList<Course>();
		ArrayList<Resource> newList = new ArrayList<Resource>();
		for (Course c : courseDAO.getListCourses()) {
			ArrayList<Resource> listResource = getListResourcesByCourse(c.getId());
			for (Resource resource : listResource) {
				resource.getCourse().setId_amadeus(c.getId_amadeus());
				if (resource.getForum().getId() != 0) {
					Forum forum = forumDAO.getForum(resource.getForum().getId());
					forum.setListMessages(messageDAO.getListMessagesByForum(forum.getId()));
					resource.setForum(forum);
				}
				newList.add(resource);
			}
			c.setResourceList(newList);
			courses.add(c);
		}
		return courses;
	}
	
	private Course getCourseByResource(int id){
		Course course = null;
		for (Course c : courseDAO.getListCourses()) {
			if (c.getId_amadeus() == id) {
				course = c;
				break;
			}
		}
		return course;
	}
	
	public void insertTask(Task task){
		this.taskDAO.save(task);
	}
	
	public void insertSocialHistory(SocialHistory socialHistory){
		this.socialHistoryDAO.save(socialHistory);
	}
	
	public void insertForumMessage(Message message){
		this.messageDAO.save(message);
	}
	
	public List<SocialHistory> getListSocialHistory(){
		return this.socialHistoryDAO.getListSocialHistory();
	}
	
	public ArrayList<Task> getTaskList(){
		return this.taskDAO.getTaskList();
	}
	
	public Task getTask(int id){
		return this.taskDAO.getTask(id);
	}

	public void insertGoal(String text, String beginDate, String endDate,
			int avgTime, int course_user_id, boolean resolved) {
		this.goalDAO = GoalDAO.getInstance(ctx);
		Goal goal = new Goal(text, beginDate, endDate, avgTime, new CourseUser(course_user_id), resolved);
		goalDAO.save(goal);
	}

	public void insertGoal(Goal goal) {
		this.goalDAO = GoalDAO.getInstance(ctx);
		goalDAO.save(goal);
	}
	
	public ArrayList<Resource> getResourceByCourse(int course_id) {
		this.resourceDAO = ResourceDAO.getInstance(ctx);
		ArrayList<Resource> resourceList = this.resourceDAO.getResourceByCourse(course_id);
		return resourceList;
	}

	public ArrayList<Action> getAllActions() {
		this.actionDAO = ActionDAO.getInstance(ctx);
		ArrayList<Action> actionList = this.actionDAO.getAllActions();
		return actionList;
	}

	
	public ArrayList<String> getAllResourceNameOfCourse(int course_id){
		ArrayList<Resource> resourceList = this.getResourceByCourse(course_id);
		ArrayList<String> srList = new ArrayList<String>();
		for (int i = 0; i < resourceList.size(); i++) {
			if(resourceList.get(i).getName() != null)
				srList.add(resourceList.get(i).getName());
		}
		return srList;
	}
	
	public ArrayList<String> getAllActionsValue(int course_id){
		ArrayList<Action> actionList = this.getAllActions();
		ArrayList<String> saList = new ArrayList<String>();
		if(actionList != null){
			for (int i = 0; i < actionList.size(); i++) {
				if(actionList.get(i).getValue() != null)
					saList.add(actionList.get(i).getValue());
			}
			return saList;
		}else{ return null;}
	}

	public ArrayList<String> getAllGoalsDefinitionOfCourse(int course_id){
		ArrayList<Goal> goalList = this.getAllGoalByCourse(course_id);
		ArrayList<String> sgList = new ArrayList<String>();
		if(goalList != null){
			for (int i = 0; i < goalList.size(); i++) {
				if(goalList.get(i).getDefinition() != null)
					sgList.add(goalList.get(i).getDefinition());
			}
			return sgList;
		}else{ return null; }
	}
	
	public Goal getGoal(int goal_id){
		this.goalDAO = GoalDAO.getInstance(ctx);
		return this.goalDAO.getGoal(goal_id);
	}
	
	public Goal getGoalFull(int goal_id){
		this.goalDAO = GoalDAO.getInstance(ctx);
		return this.goalDAO.getGoalWithCouseUser(goal_id);
	}

	public void updateCourse(Course course) {
		this.courseDAO.save(course);
		
	}
	
	public ArrayList<Task> getAllTasksByGoal(int goal_id){
		return this.taskDAO.getAllTasksByGoal(goal_id);
	}

	public Resource getResource(int id) {
		return this.resourceDAO.getResource(id);
	}
	
	public Action getAction(int id) {
		return this.actionDAO.getAction(id);
	}
}